package com.come4loves.core.utils;

import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.come4loves.core.context.SpringContext;

public class HttpUtils {
	private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);

//	private static ThreadSafeClientConnManager cm;
	private static PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
	private static CloseableHttpClient httpclient;
	
	private static RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(30000).setConnectTimeout(30000).build();//设置请求和传输超时时间
	
	static {
		
		try {
			SSLContext ctx = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				
				@Override
				public boolean isTrusted(X509Certificate[] arg0, String arg1)
						throws CertificateException {
					return true;
				}
			}).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx);
			httpclient = HttpClients.custom().setConnectionManager(cm).setSSLSocketFactory(sslsf).build();
			Integer maxTotal = (Integer) SpringContext.getBean("httputil.maxtotal");
			cm.setMaxTotal(maxTotal);
			Integer connectionTimeout = (Integer) SpringContext.getBean("httputil.connection.timeout");
			Integer soTimeout = (Integer) SpringContext.getBean("httputil.so.timeout");
			requestConfig = RequestConfig.custom().setSocketTimeout(soTimeout).setConnectTimeout(connectionTimeout).build();//设置请求和传输超时时间
			
			

			
		} catch (Exception e) {
			LOGGER.error("{}", e);
		} 
		
	}
	
	public static String sendGet(String url, Map<String, String> params, boolean encodeParams) {
		return sendGet(url, map2Prefix(params, encodeParams));
	}

	public static String sendGet(String url, Map<String, String> params) {
		return sendGet(url, map2Prefix(params, false));
	}
	
	public static String sendGet(String url, String prefix) {
		if (StringUtils.isNotBlank(prefix)) {
			if (url.indexOf("?") < 1) {
				url += "?";
			}
		}
		return sendGet(url.concat(prefix));
	}

	/**
	 * 向指定URL发送GET方法的请求
	 * @param urlPath	已拼合好的url地址
	 * @return
	 */
	public static String sendGet(String urlPath) {
		try {			
			HttpGet httpget = new HttpGet(urlPath);
			httpget.setConfig(requestConfig);
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug(String.format("httputil request url:[%s] ", urlPath));
			}
			CloseableHttpResponse response = httpclient.execute(httpget);
			HttpEntity entity = null;
			try {
				entity = response.getEntity();
				return EntityUtils.toString(entity);
			} finally {
				if (LOGGER.isDebugEnabled()) {
					int statusCode = response.getStatusLine().getStatusCode();
					LOGGER.debug(String.format("url:[%s] status:[%s]", urlPath, statusCode));
				}
				if(entity != null) {
					EntityUtils.consume(entity);	
				}
				response.close();
				
			}
		} catch (Exception e) {
			LOGGER.error("{}", e);
		}
		return "";
	}
	
	/**
	 * 向指定 URL 发送POST方法的请求
	 * @param url		发送请求的 URL
	 * @param params	post的字符串
	 * @return
	 */
	public static String sendPost(String url, String params) {
		try {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			httpPost.setEntity(new ByteArrayEntity(params.getBytes("UTF-8")));
			CloseableHttpResponse response = httpclient.execute(httpPost);
			HttpEntity entity = null;
			try {
				entity = response.getEntity();
				return EntityUtils.toString(entity);
			} finally {
				int statusCode = response.getStatusLine().getStatusCode();
				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug(String.format("url:[%s] prefix:[%s] status:[%s]", url, params, statusCode));
				}
				if (entity != null) {
					EntityUtils.consume(entity);
				}
				
				response.close();

			}
		} catch (Exception e) {
			LOGGER.error("{}", e);
		}
		return "";
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 * @param url		发送请求的 URL
	 * @param param		请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, Map<String, String> paramsMaps) {
		try {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
			for (Map.Entry<String, String> entry : paramsMaps.entrySet()) {
				nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
			}
			
			httpPost.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));
			CloseableHttpResponse response = httpclient.execute(httpPost);
			HttpEntity entity = null;
			try {
				entity = response.getEntity();
				return EntityUtils.toString(entity);
			} finally {
				int statusCode = response.getStatusLine().getStatusCode();
				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug(String.format("url:[%s] prefix:[%s] status:[%s]", url, map2Prefix(paramsMaps, false), statusCode));
				}
				if (entity != null) {
					EntityUtils.consume(entity);
				}
				response.close();
				
			}
		} catch (Exception e) {
			LOGGER.error("{}", e);
		}
		return "";
	}

	public static String map2Prefix(Map<String, String> data, boolean encodeParams) {
		StringBuilder sb = new StringBuilder();
		try {

			for (Entry<String, String> entry : data.entrySet()) {
				if (encodeParams) {
					sb.append("&" + entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), "utf-8"));
				} else {
					sb.append("&" + entry.getKey() + "=" + entry.getValue());
				}
			}

			if (sb.length() > 1) {
				return sb.substring(1).toString();
			}
			return "";
		} catch (Exception ex) {
			LOGGER.warn("{}", ex);
		}
		return "";
	}
	

}
